Exercise 02.1 (if-else)

Consider the following assessment criteria which map a score out of 100 to an assessment grade:

Grade Raw score (/100)
Excellent $\ge 82$
Very good $\ge 76.5$ and $< 82$
Good $\ge 66$ and $< 76.5$
Need improvement $\ge 45$ and $< 66$
Did you try? $< 45$

Write a program that asks for the input score and prints the appropriate grade. Print an error message if the input score is greater than 100 or less than zero.

Recall that

# Get input from user
number = float(input('How many seconds in one minute? '))

can be used for interactive input.


In [1]:
# Get input from user
score = float(input('What\'s your score? '))

if score < 0 or score > 100:
    print('Score must be between 0 and 100')
elif score < 45:
    print('Did you try?')
elif score < 66:
    print('Need improvement')
elif score < 76.5:
    print('Good')
elif score < 82:
    print('Very good')
else:
    print('Excellent')


What's your score? 75
Good

Exercise 02.2 (bisection)

Bisection is an iterative method for approximating roots of a function. Say we know that the function $f(x)$ has one root between $x_{0}$ and $x_{1}$ ($x_{0} < x_{1}$). We then:

  • Evaluate $f$ at the midpoint $x_{\rm mid} = (x_0 + x_1)/2$, i.e. compute $f_{\rm mid} = f(x_{\rm mid})$
  • Evaluate $f(x_0) \cdot f(x_{\rm mid})$

    • If $f(x_0) \cdot f(x_{\rm mid}) < 0$:

      $f$ must change sign somewhere between $x_0$ and $x_{\rm mid}$, hence the root must lie between $x_0$ and $x_{\rm mid}$, so set $x_1 = x_{\rm mid}$.

    • Else

      $f$ must change sign somewhere between $x_{\rm mid}$ and $x_1$, so set $x_0 = x_{\rm mid}$.

The above steps can be repeated a specified number of times, or until $|f_{\rm mid}|$ is below a tolerance, with $x_{\rm mid}$ being the approximate root.

Task: The function

$$ f(x) = x^3 - 6x^2 + 4x + 12 $$

has one root somewhere between $x_0 = 3$ and $x_1 = 6$.

  1. Use the bisection method to find an approximate root $x_{r}$ using 15 iterations (use a for loop).
  2. Use the bisection method to find an approximate root $x_{r}$ such that $\left| f(x_{r}) \right| < 1 \times 10^{-6}$ and report the number of iterations required (use a while loop).

Hint: Use abs to compute the absolute value of a number, e.g. y = abs(x) assigns the absolute value of x to y.

Approximate root using 15 iterations


In [2]:
# Number of iterations to do
n_iter = 15

# Initialize x_0 and x_1
x_0 = 3
x_1 = 6

for i in range(n_iter):
    
    # Compute x_mid
    x_mid = (x_0 + x_1) / 2
    
    # Compute f for the three values
    f_0 = x_0**3 - 6*x_0**2 + 4*x_0 + 12
    f_1 = x_1**3 - 6*x_1**2 + 4*x_1 + 12
    f_mid = x_mid**3 - 6*x_mid**2 + 4*x_mid + 12
    
    # Check the value of f_0*f_mid to determine how to update the endpoints
    if f_0*f_mid < 0:
        x_1 = x_mid
    else:
        x_0 = x_mid

print('Approximated root:', x_mid)


Approximated root: 4.534149169921875

Approximate root under $1 \times 10^{-6}$ tolerance


In [3]:
# Desired precision
prec = 1e-6
# Counter for number of iterations
n_iter = 0

# Initialize x_0 and x_1
x_0 = 3
x_1 = 6

while(True):
    
    # Update the number of iterations
    n_iter += 1
    
    # Compute x_mid
    x_mid = (x_0 + x_1) / 2
    
    # Compute f for the three values
    f_0 = x_0**3 - 6*x_0**2 + 4*x_0 + 12
    f_1 = x_1**3 - 6*x_1**2 + 4*x_1 + 12
    f_mid = x_mid**3 - 6*x_mid**2 + 4*x_mid + 12
    
    # Check the value of f_0*f_mid to determine how to update the endpoints
    if f_0*f_mid < 0:
        x_1 = x_mid
    else:
        x_0 = x_mid
    
    # Check if the desired precision is reached and break
    if abs(f_mid) < prec:
        break

print('Approximated root:', x_mid)
print('Number of iterations required:', n_iter)


Approximated root: 4.534070134162903
Number of iterations required: 23

Exercise 02.3 (series expansion)

The power series expansion for sine is:

$$ \sin(x) = \sum_{n = 0}^{\infty} (-1)^n \frac{x^{2n +1}}{(2n+1)!} $$

(See mathematics data book for a less compact version; the compact version is preferred here as it is simpler to program.)

  1. Using a for statement, approximate $\sin(3\pi/2)$ using 15 terms in the series exansion and report the absolute error.

  2. Using a while statement, compute how many terms in the series are required to approximate $\sin(3\pi/2)$ to within $1 \times 10^{-8}$.

Note: Calculators and computers use iterative or series expansions to compute trigonometric functions, similar to the one above (although they use more efficient formulations than the above series).

Hints

To compute the factorial and to get a good approximation of $\pi$, use the Python math module:

import math
nfact = math.factorial(10)
pi = math.pi

You only need 'import math' once at the top of your program. Standard modules, like math will be explained in a later exercise. If you want to test for angles for which sine is not simple, you can use

a = 1.3
s = math.sin(a)

to get an accurate computation of sine to check the error.


In [4]:
# Import math module to compute factorial and sine
import math

Taylor series with 15 terms


In [5]:
# Number of iterations to do
n_terms = 15

# Initialize x and its sine
x = 3*math.pi/2
sin_x = 0

for i in range(n_terms):
    
    # Add the next term to the summatory
    sin_x += (-1)**i * (x**(2*i+1) / math.factorial(2*i+1))

print('Calculated sine:', sin_x)
print('Absolute error:', abs(sin_x - math.sin(x)))


Calculated sine: -0.9999999999999121
Absolute error: 8.79296635503124e-14

Number of terms required to approximate sine under $1 \times 10^{-8}$ precision


In [6]:
# Desired precision
prec = 1e-8

# Initialize x, its sine, the "real" sine and the number of terms used
x = 3*math.pi/2
sin_x = 0
true_sin_x = math.sin(x)
n_terms = 0

# Initialize the counter
i = 0

while(True):
    
    # Update the number of terms
    n_terms += 1
    
    # Add the next term to the summatory
    sin_x += (-1)**i * (x**(2*i+1) / math.factorial(2*i+1))
    
    # Update counter
    i += 1
    
    # Check if the desired precision is reached and break
    if abs(sin_x - true_sin_x) < prec:
        break

print('Calculated sine:', sin_x)
print('Number of terms required:', n_terms)


Calculated sine: -1.0000000042344912
Number of terms required: 12